package com.matrix.gui;

import java.text.DecimalFormat;
import java.util.ArrayList;

import com.matrix.math.ColumnVector;
import com.matrix.math.MathObject;
import com.matrix.math.Matrix;
import com.matrix.utils.FileIO;

import android.app.Activity;
import android.app.Dialog;
import android.content.Context;
import android.graphics.Color;
import android.graphics.Rect;
import android.os.Bundle;
import android.text.TextPaint;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.Gravity;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnCreateContextMenuListener;
import android.view.Window;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TableLayout;
import android.widget.TableRow;
import android.widget.TextView;
/**
 * Results View 
 * Android activity for displaying the results of the matrix operations.
 * @author McGarvie
 *
 */
public class ResultView extends Activity {

	/**
	 * the formated string version of the matrix
	 */
	private String[][] strmtrx;
	/**
	 * the max length in pixels that the largest string int he matrix takes up
	 */
	private int[] maxColLength;
	/**
	 * gets the global variables
	 */
	private Globals global;
	private Alert dialog;
    /** Called when the activity is first created. */
	protected void onCreate(Bundle savedInstanceState) 
	{
		super.onCreate(savedInstanceState);
		setContentView(R.layout.result);
		TableLayout aTable=(TableLayout)findViewById(R.id.matrix);
		global =(Globals) this.getApplicationContext();
		dialog = new Alert(this);
		//prints the result of the operations to the screen
		try{
			ArrayList<Matrix> resultMatrix = global.getResultMatrix();
			switch(global.getOpType())
			{
			case 0: 
				//getMatrix gets on of the matrices out of the bundle
				//this.appendRows(aTable, resultMatrix.get(0));
				addMatrix(aTable, 0);
				break;
			case 5: 
				this.plu(aTable, resultMatrix);
				break;
			case 6: 
				addMatrix(aTable, 6);
				break;
			case 8:
				addMatrix(aTable, 8);
				break;
			default:
				addMatrix(aTable,10);
				
			}
		}catch(Exception e)
		{
			
		}
		
	}
	/**
	 * prints the matrix or vectors out differently based on the operation 
	 * that was performed
	 * @param table
	 * @param op
	 */
	public void addMatrix(TableLayout table, int op)
	{
		TableRow row = new TableRow(this);
		TextView c = new TextView(this);
		
		ResultsDrawable r;
		ArrayList<ColumnVector> vList = global.getResultColVector();
		switch(op)
		{
		case 0: //ops resulting in a single matrix
			Matrix m = global.getResultMatrix().get(0);
			setStringMatrix(m);
			c.setText(m.getName());
			c.setPadding(3, 3, 3, 3);
			c.setTextSize(20);
			c.setTextColor(Color.BLACK);
			//adds the textView to the row
			row.addView(c);
			table.addView(row, new TableLayout.LayoutParams());
			row = new TableRow(this);
			r = new ResultsDrawable(this, strmtrx, maxColLength,m);
			addContextInflater(r);
			row.addView(r, r.width()+25, r.height());
			table.addView(row, new TableLayout.LayoutParams());
			break;
		case 6://the Ax=b solve function
			c.setText("Ax=b");
			c.setPadding(3, 3, 3, 3);
			c.setTextSize(20);
			c.setTextColor(Color.BLACK);
			//adds the textView to the row
			row.addView(c);
			table.addView(row, new TableLayout.LayoutParams());
			row = new TableRow(this);
			for(int i=0; i<vList.size(); i++)
			{
				ColumnVector v = global.getResultColVector().get(i);
				setStringVector(v);
				r = new ResultsDrawable(this, strmtrx, maxColLength, v);
				addContextInflater(r);
				row.addView(r, r.width()+25, r.height());
				if(i<vList.size()-1)
				{
					c = new TextView(this);
					c.setText("+ C"+i);
					c.setPadding(3, 3, 3, 3);
					c.setTextSize(20);
					c.setTextColor(Color.BLACK);
					//adds the textView to the row
					row.addView(c);
					row.setGravity(Gravity.CENTER_VERTICAL);
				}
			}
			table.addView(row, new TableLayout.LayoutParams());
			break;
		case 8://ops resulting in a single vector
			ColumnVector v = global.getResultColVector().get(0);
			c.setText(v.getName());
			c.setPadding(3, 3, 3, 3);
			c.setTextSize(20);
			c.setTextColor(Color.BLACK);
			//adds the textView to the row
			row.addView(c);
			table.addView(row, new TableLayout.LayoutParams());
			row = new TableRow(this);
			setStringVector(v);
			r = new ResultsDrawable(this, strmtrx, maxColLength, v);
			addContextInflater(r);
			row.addView(r, r.width()+25, r.height());
			table.addView(row, new TableLayout.LayoutParams());
			break;
		default://the null space 
			c.setText("Null Vectors");
			c.setPadding(3, 3, 3, 3);
			c.setTextSize(20);
			c.setTextColor(Color.BLACK);
			//adds the textView to the row
			row.addView(c);
			table.addView(row, new TableLayout.LayoutParams());
			row = new TableRow(this);
			for(int i=0; i<vList.size(); i++)
			{
				v = global.getResultColVector().get(i);
				setStringVector(v);
				r = new ResultsDrawable(this, strmtrx, maxColLength, v);
				addContextInflater(r);
				row.addView(r, r.width()+25, r.height());
			}
			table.addView(row, new TableLayout.LayoutParams());
		}
		
	}
	public void addContextInflater(ResultsDrawable r)
	{
		r.setOnCreateContextMenuListener(new OnCreateContextMenuListener()
		{

			@Override
			public void onCreateContextMenu(ContextMenu menu, View v,
					ContextMenuInfo menuInfo) {
				// TODO Auto-generated method stub
				MenuInflater infl = getMenuInflater();
				infl.inflate(R.menu.save_menu, menu);
				dialog.setMathObject(((ResultsDrawable) v).getMathObject());
				
			}
			
		});
	}
	public boolean onContextItemSelected(MenuItem item) {
		
		switch(item.getItemId())
		{
			case R.id.menu_context_save:
				dialog.ask("Save", "Cancel");
				dialog.setSave(true);
				break;
			case R.id.menu_context_set:
				dialog.ask("Set", "Cancel");
				dialog.setSave(false);
				break;
		}
		return false;
	}

	/**
	 * sets the formatted string matrix and the max column length array for a matrix
	 * @param m
	 */
	public void setStringMatrix(com.matrix.math.Matrix m)
	{
		String temp;
		strmtrx = new String[m.numRows()][m.numCols()];
		maxColLength = new int[m.numCols()];
		Rect r = new Rect();
		TextPaint tp = new TextPaint();
		int scaledSize = getResources().getDimensionPixelSize(R.dimen.font_size);
		tp.setTextSize(scaledSize);
		for(int i=0; i<strmtrx[0].length; i++)
		{
			maxColLength[i] =0;
			for(int j=0; j<strmtrx.length; j++)
			{
				try {
					temp = formatDouble(m.getValueAt(j, i)); 
					tp.getTextBounds(temp, 0, temp.length(), r);
					if(r.width()>maxColLength[i])
					{
						maxColLength[i] = r.width();
					}
					strmtrx[j][i] = temp;
					
				} catch (Exception e) {
				}
			}
		}
	}
	/**
	 * sets the formatted string matrix and the max column length array for a vector
	 * @param v
	 */
	public void setStringVector(ColumnVector v)
	{
		String temp;
		strmtrx = new String[v.length()][1];
		maxColLength = new int[1];
		Rect r = new Rect();
		TextPaint tp = new TextPaint();
		int scaledSize = getResources().getDimensionPixelSize(R.dimen.font_size);
		tp.setTextSize(scaledSize);
		for(int i=0; i<strmtrx[0].length; i++)
		{
			maxColLength[i] =0;
			for(int j=0; j<strmtrx.length; j++)
			{
				try {
					temp = formatDouble(v.getValueAt(j)); 
					tp.getTextBounds(temp, 0, temp.length(), r);
					if(r.width()>maxColLength[i])
					{
						maxColLength[i] = r.width();
					}
					strmtrx[j][i] = temp;
					
				} catch (Exception e) {
				}
			}
		}
	}
	/**
	 * formats the double 
	 * @param d
	 * @return
	 */
	private String formatDouble(double d)
	{
		String format = d+"";
		DecimalFormat df;
		if(format.length() > 8)
		{
			if((d<1&&d>0)||(d>-1&&d<0))
			{
				df = new DecimalFormat("0.00E0");
				format = df.format(d);
			}
			else
			{
				if(d>99999999 || d<-9999999)
				{
					df = new DecimalFormat("0.00E0");
					format = df.format(d);
				}
				else
				{
					if(format.contains("E"))
					{
						df = new DecimalFormat("0.00E0");
						format = df.format(d);
					}
					else
					{
						int i = format.lastIndexOf('.')+1;
						if(i==8)
						{
							df = new DecimalFormat("0");
							format = df.format(d);
						}
						else
						{
							String f = "0.";
							//System.out.println(i);
							for(int j=i; j<8; j++)
							{
								f += "0";
							}
							//System.out.println(f);
							df = new DecimalFormat(f);
							format = df.format(d);
						}
					}
				}
			}
		}
		return format;
	}
	/**
	 * inserts the plu factorization of the matrix into the result view
	 * @param table
	 * @param plu
	 */
	public void plu(TableLayout table, ArrayList<com.matrix.math.Matrix> plu) 
	{
		TableRow row = new TableRow(this);
		TextView c = new TextView(this);
		ResultsDrawable r;
		com.matrix.math.Matrix m = global.getResultMatrix().get(0);
		setStringMatrix(m);
		c.setText("Matrix "+m.getName());
		c.setPadding(3, 3, 3, 3);
		c.setTextSize(20);
		c.setTextColor(Color.BLACK);
		//adds the textView to the row
		row.addView(c);
		table.addView(row, new TableLayout.LayoutParams());
		row = new TableRow(this);
		r = new ResultsDrawable(this, strmtrx, maxColLength, m);
		addContextInflater(r);
		row.addView(r, r.width()+25, r.height());
		table.addView(row, new TableLayout.LayoutParams());
		
		m = global.getResultMatrix().get(1);
		setStringMatrix(m);
		c = new TextView(this);
		c.setText("Matrix "+m.getName());
		c.setPadding(3, 3, 3, 3);
		c.setTextSize(20);
		c.setTextColor(Color.BLACK);
		//adds the textView to the row
		row = new TableRow(this);
		row.addView(c);
		table.addView(row, new TableLayout.LayoutParams());
		row = new TableRow(this);
		r = new ResultsDrawable(this, strmtrx, maxColLength, m);
		addContextInflater(r);
		row.addView(r, r.width()+25, r.height());
		table.addView(row, new TableLayout.LayoutParams());
		
		m = global.getResultMatrix().get(2);
		setStringMatrix(m);
		c = new TextView(this);
		c.setText("Matrix "+m.getName());
		c.setPadding(3, 3, 3, 3);
		c.setTextSize(20);
		c.setTextColor(Color.BLACK);
		//adds the textView to the row
		row = new TableRow(this);
		row.addView(c);
		table.addView(row, new TableLayout.LayoutParams());
		row = new TableRow(this);
		r = new ResultsDrawable(this, strmtrx, maxColLength, m);
		addContextInflater(r);
		row.addView(r, r.width()+25, r.height());
		table.addView(row, new TableLayout.LayoutParams());
	}
	
	
	/**
	 * inner class for dialog
	 * @author Sultan
	 *
	 */
	class Alert extends Dialog
	{
		/**
		 * instance variables
		 */
		private	Button btn1, btn2, ok;
		private TextView title; 
		private EditText name;
		private boolean save;
		MainActivity mat;
		private MathObject m;
		// constructor
		public Alert(Context context)
		{
			super(context);
			this.requestWindowFeature(Window.FEATURE_NO_TITLE);
			setContentView(R.layout.resultdialog);
			this.init();
			this.setListeners();
		}
		// methods
		public void init()
		{
			this.btn1 = (Button) findViewById(R.id.dialog_box12);
			this.btn2 = (Button) findViewById(R.id.dialog_box22);
			this.ok = (Button)   findViewById(R.id.dialog_ok2);
			this.title = (TextView) findViewById(R.id.dialog_title2);
			this.name = (EditText) findViewById(R.id.dialog_text2);
		}
		public void setListeners()
		{
			this.btn1.setOnClickListener(new Button.OnClickListener()
			{
				public void onClick(View v)
				{
					dismiss();
					MathObject temp = m.clone();
					if(save)
					{
						FileIO f = new FileIO();
						
						try {
							temp.setName(name.getText().toString());
							f.saveMatrix(name.getText().toString(), temp);
						} catch (Exception e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
					}
					else
					{
						temp.setName(name.getText().toString());
						global.getListItems().add(temp);
					}
				}
			});
			this.btn2.setOnClickListener(new Button.OnClickListener()
			{
				public void onClick(View v)
				{
					dismiss();
				}
			});
			
			this.ok.setOnClickListener(new Button.OnClickListener()
			{
				public void onClick(View v)
				{
					dismiss();
				}	
			});
		}
		
		public void setTitle(String title)
		{
			this.title.setText(title);
		}
		public void show(String title, String message)
		{
			this.btn1.setVisibility(Button.GONE);
			this.btn2.setVisibility(Button.GONE);
			this.ok.setVisibility(Button.VISIBLE);
			setTitle(title);
			show();
		}
		public void error(String message)
		{
			this.show("ERROR", message);
		}
		public void ask(String first, String second)
		{
			this.btn1.setVisibility(Button.VISIBLE);
			this.btn2.setVisibility(Button.VISIBLE);
			this.ok.setVisibility(Button.GONE);
			this.btn1.setText(first);
			this.btn2.setText(second);
			this.setTitle(first);
			
			show();
		}
		public void setMathObject(MathObject mo)
		{
			m = mo;
		}
		public void view(String message)
		{
			this.show("View", message);
		}
		public void setSave(boolean b)
		{
			save = b;
		}
	}
}
 


